package org.ala.tiktools.redis.config;


import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;

/**
 * 解析配置项
 *
 * @author ala
 * @date 2024-11-27 15:17
 */
public class Configuration {

    /**
     * 配置项前缀
     */
    public static final String PREFIX = "redis";
    /**
     * 模版key
     */
    public static final String TEMPLATE = "template";
    /**
     * Bean名称前缀
     */
    public static final String PREFIX_BEAN_NAME = "RedisTool";

    /**
     *  解析配置项
     */
    public Map<String, ConfigItem> parse(Environment env) {
        MutablePropertyValues pvs = subProperties(env, PREFIX);
        ConfigItem def = parseItem(pvs, TEMPLATE, null);
        Set<String> set = parseNames(pvs);
        return set.stream().collect(Collectors.toMap(k -> k, k -> parseItem(pvs, k, def), (o,n)->n));
    }
    /**
     * 获取子参数集
     * @param env 环境上下文
     * @param pre 参数前缀
     * @return 子参数集
     */
    @SuppressWarnings("rawtypes")
    public static MutablePropertyValues subProperties(Environment env, String pre) {
        MutablePropertyValues mpvs = new MutablePropertyValues();
        Collection<String> ns = new HashSet<>();
        for (PropertySource<?> propertySource : ((AbstractEnvironment) env).getPropertySources()) {
            if (propertySource instanceof EnumerablePropertySource) {
                String[] propertyNames = ((EnumerablePropertySource) propertySource).getPropertyNames();
                for (String name : propertyNames) {
                    if (name.startsWith(pre)) {
                        if (!ns.add(name)) continue;
                        mpvs.addPropertyValue(name, env.getProperty(name));
                    }
                }
            }
        }
        return mpvs;
    }


    /**
     *  解析全部redis配置项名称
     */
    protected Set<String> parseNames(MutablePropertyValues pvs) {
        Set<String> set = new HashSet<>();
        for (PropertyValue pv : pvs.getPropertyValues()) {
            String name = pv.getName();
            if (name.startsWith(PREFIX + "." + TEMPLATE + ".")) {continue;}

            String[] ss = pv.getName().split("\\.");
            set.add(ss[1]);
        }
        return set;
    }
    /**
     *  解析配置项
     */
    protected ConfigItem parseItem(MutablePropertyValues pvs, String name, ConfigItem def) {
        ConfigItem item = new ConfigItem();
        try { item.setHost(pvs.getPropertyValue(PREFIX + "." + name + ".host").getValue().toString()); }
        catch (Exception e) { if (def != null) {item.setHost(def.getHost());} }

        try { item.setPort(Integer.parseInt(pvs.getPropertyValue(PREFIX + "." + name + ".port").getValue().toString())); }
        catch (Exception e) { if (def != null) {item.setPort(def.getPort());} }

        try { item.setPassword(pvs.getPropertyValue(PREFIX + "." + name + ".password").getValue().toString()); }
        catch (Exception e) { if (def != null) {item.setPassword(def.getPassword());} }

        try { item.setTimeout(Integer.parseInt(pvs.getPropertyValue(PREFIX + "." + name + ".timeout").getValue().toString())); }
        catch (Exception e) { if (def != null) {item.setTimeout(def.getTimeout());} }

        try { item.setDatabase(Integer.parseInt(pvs.getPropertyValue(PREFIX + "." + name + ".database").getValue().toString())); }
        catch (Exception e) { if (def != null) {item.setDatabase(def.getDatabase());} }

        try { item.setPoolIdle(Integer.parseInt(pvs.getPropertyValue(PREFIX + "." + name + ".poolIdle").getValue().toString())); }
        catch (Exception e) { if (def != null) {item.setPoolIdle(def.getPoolIdle());} }

        try { item.setPoolMax(Integer.parseInt(pvs.getPropertyValue(PREFIX + "." + name + ".poolMax").getValue().toString())); }
        catch (Exception e) { if (def != null) {item.setPoolMax(def.getPoolMax());} }
        return item;
    }
}
